/**
 * Copyright 2011 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.api.adwords.starterkit.wrappers;

import com.google.api.adwords.starterkit.db.keys.KeywordKey;
import com.google.api.adwords.starterkit.db.structures.KeywordStructure;
import com.google.api.adwords.starterkit.db.tables.KeywordTable;
import com.google.api.adwords.starterkit.settings.KeywordSettings;
import com.google.api.adwords.v201101.cm.KeywordMatchType;
import com.google.api.adwords.v201101.cm.UserStatus;

import java.sql.Connection;

/**
 * The Class KeywordWrapper manages all synchronization process related to
 * Keywords on the DB.
 * 
 * @author rodrigo.f.vale@gmail.com
 */
public class KeywordWrapper {
  private KeywordStructure kwdStructure;

  private KeywordSettings keywordSettings;
  private Connection conn = null;

  private KeywordParamWrapper keywordParamWrapper = null;
  private KeywordTable keywordTable;

  /**
   * Instantiates a new keyword wrapper.
   * 
   * @param adgroupWrapper the adgroup wrapper
   * @param text the keyword text
   * @param negative the keyword negative flag
   * @param destUrl the keyword dest url
   * @param keywordSettings the starter kit settings
   * @param conn the DB connection
   */
  public KeywordWrapper(final AdGroupWrapper adgroupWrapper, final String text,
      boolean negative, String destUrl, final KeywordSettings keywordSettings,
      Connection conn) {
    this.conn = conn;
    this.keywordSettings = keywordSettings;
    kwdStructure = new KeywordStructure();

    kwdStructure.setText(text);
    kwdStructure.setStatus(keywordSettings.getStatus());
    kwdStructure.setMaxCpc(keywordSettings.getCpc());
    kwdStructure.setMaxCpm(keywordSettings.getCpm());
    kwdStructure.setMatchType(keywordSettings.getMatchType());
    kwdStructure.setDestinationUrl(destUrl);
    kwdStructure.setNegative(negative);

    kwdStructure.setAdGroupId(adgroupWrapper.getAdGroupId());
    kwdStructure.setLocalAdGroupId(adgroupWrapper.getLocalId());

    kwdStructure.setCpcModifiable(true);
    kwdStructure.setMatchModifiable(true);
    kwdStructure.setStatusModifiable(true);
    kwdStructure.setUrlModifiable(true);

    keywordTable = new KeywordTable(conn);

    KeywordKey keywordKey =
        new KeywordKey(kwdStructure.getLocalAdGroupId(), kwdStructure.getText(),
            kwdStructure.getMatchType());
    if (keywordTable.exists(keywordKey)) {
      synchronize(keywordKey);
    } else {
      kwdStructure = keywordTable.save(kwdStructure, true, true);
    }
    keywordTable.setTouched(keywordKey, true);
  }

  public int getLocalId() {
    return kwdStructure.getLocalId();
  }

  public int getLocalAdGroupId() {
    return kwdStructure.getLocalAdGroupId();
  }

  public long getAdGroupId() {
    return kwdStructure.getAdGroupId();
  }

  public long getMaxCpc() {
    return kwdStructure.getMaxCpc();
  }

  public long getMaxCpm() {
    return kwdStructure.getMaxCpm();
  }

  public String getDestUrl() {
    return kwdStructure.getDestinationUrl();
  }

  public KeywordMatchType getMatchType() {
    return kwdStructure.getMatchType();
  }

  public UserStatus getStatus() {
    return kwdStructure.getStatus();
  }

  public String getText() {
    return kwdStructure.getText();
  }

  public boolean getNegative() {
    return kwdStructure.isNegative();
  }

  public void setLocalId(int localId) {
    kwdStructure.setLocalId(localId);
    keywordTable.save(kwdStructure, true, true);
  }

  public void setkeywordId(long keywordId) {
    kwdStructure.setKeywordId(keywordId);
    keywordTable.save(kwdStructure, true, true);
  }

  public void setLocalAdGroupId(int localAdGroupId) {
    kwdStructure.setLocalAdGroupId(localAdGroupId);
    keywordTable.save(kwdStructure, true, true);
  }

  public void setAdGroupId(long adGroupId) {
    kwdStructure.setAdGroupId(adGroupId);
    keywordTable.save(kwdStructure, true, true);
  }

  public void setDestUrl(String destinationUrl) {
    kwdStructure.setDestinationUrl(destinationUrl);
    keywordTable.save(kwdStructure, true, true);
  }

  public void setMaxCpc(long maxCpc) {
    kwdStructure.setMaxCpc(maxCpc);
    keywordTable.save(kwdStructure, true, true);
  }

  public void setMaxCpm(long maxCpm) {
    kwdStructure.setMaxCpm(maxCpm);
    keywordTable.save(kwdStructure, true, true);
  }

  public void setMatchType(KeywordMatchType matchType) {
    kwdStructure.setMatchType(matchType);
    keywordTable.save(kwdStructure, true, true);
  }

  public void setNegative(boolean negative) {
    kwdStructure.setNegative(negative);
    keywordTable.save(kwdStructure, true, true);
  }

  public void setStatus(UserStatus status) {
    kwdStructure.setStatus(status);
    keywordTable.save(kwdStructure, true, true);
  }

  public void setText(String text) {
    kwdStructure.setText(text);
  }

  public boolean getCanModifyStatus() {
    return kwdStructure.isStatusModifiable();
  }

  public boolean getCanModifyMatch() {
    return kwdStructure.isMatchModifiable();
  }

  public boolean getCanModifyCpc() {
    return kwdStructure.isCpcModifiable();
  }

  public boolean getCanModifyUrl() {
    return kwdStructure.isUrlModifiable();
  }

  /**
   * Sets the can modify status flag. If set to false, StarterKit will not
   * modify the Keyword Status even when direct requested by application.
   * See the canModifyXXXFlags at the manual for a deep dive explanation. 
   */
  public void setCanModifyStatus(boolean canModifyStatus) {
    kwdStructure.setStatusModifiable(canModifyStatus);
    keywordTable.save(kwdStructure, false, false);
  }

  /**
   * Sets the can modify match flag. If set to false, StarterKit will not
   * modify the Keyword Match even when direct requested by application.
   * See the canModifyXXXFlags at the manual for a deep dive explanation. 
   */
  public void setCanModifyMatch(boolean canModifyMatch) {
    kwdStructure.setMatchModifiable(canModifyMatch);
    keywordTable.save(kwdStructure, false, false);
  }

  /**
   * Sets the can modify CPC flag. If set to false, StarterKit will not
   * modify the Keyword CPC even when direct requested by application.
   * See the canModifyXXXFlags at the manual for a deep dive explanation. 
   */
  public void setCanModifyCpc(boolean canModifyCpc) {
    kwdStructure.setCpcModifiable(canModifyCpc);
    keywordTable.save(kwdStructure, false, false);
  }

  /**
   * Sets the can modify URL flag. If set to false, StarterKit will not
   * modify the Keyword URL even when direct requested by application.
   * See the canModifyXXXFlags at the manual for a deep dive explanation. 
   */
  public void setCanModifyUrl(boolean canModifyUrl) {
    kwdStructure.setUrlModifiable(canModifyUrl);
    keywordTable.save(kwdStructure, false, false);
  }

  /**
   * Synchronize the current Keyword with a Keyword on DB.
   * 
   * @param keywordKey the keyword key
   */
  public void synchronize(KeywordKey keywordKey) {
    KeywordStructure oldkwd = keywordTable.get(keywordKey);

    kwdStructure.setLocalId(oldkwd.getLocalId());
    kwdStructure.setKeywordId(oldkwd.getKeywordId());
    kwdStructure.setLocalAdGroupId(oldkwd.getLocalAdGroupId());
    kwdStructure.setAdGroupId(oldkwd.getAdGroupId());
    kwdStructure.setBanned(oldkwd.isBanned());

    boolean modified = false;

    if (keywordSettings.getCanModifyBid() && !kwdStructure.isNegative()) {
      if (kwdStructure.getMaxCpc() != oldkwd.getMaxCpc()) {
        if (!oldkwd.isCpcModifiable()) {
          kwdStructure.setMaxCpc(oldkwd.getMaxCpc());
        } else {
          modified = true;
        }
      }
      if (kwdStructure.getMaxCpm() != oldkwd.getMaxCpm()) {
        if (!oldkwd.isCpcModifiable()) {
          kwdStructure.setMaxCpm(oldkwd.getMaxCpm());
        } else {
          modified = true;
        }
      }
    } else {
      kwdStructure.setMaxCpc(oldkwd.getMaxCpc());
      kwdStructure.setMaxCpm(oldkwd.getMaxCpm());
    }

    if ((keywordSettings.getCanModifyStatus())
        && (!kwdStructure.getStatus().equals(oldkwd.getStatus()))
        && !kwdStructure.isNegative()) {
      if (!oldkwd.isStatusModifiable()) {
        kwdStructure.setStatus(oldkwd.getStatus());
      } else {
        modified = true;
      }
    } else {
      kwdStructure.setStatus(oldkwd.getStatus());
    }

    if ((keywordSettings.getCanModifyUrl())
        && (!kwdStructure.getDestinationUrl()
            .equals(oldkwd.getDestinationUrl()))
        && !kwdStructure.isNegative()) {
      if (!oldkwd.isUrlModifiable()) {
        kwdStructure.setDestinationUrl(oldkwd.getDestinationUrl());
      } else {
        modified = true;
      }
    } else {
      kwdStructure.setDestinationUrl(oldkwd.getDestinationUrl());
    }

    if (modified) {
      keywordTable.save(kwdStructure, true, true);
    }
  }

  /**
   * Gets the keywordparam wrapper.
   * 
   * @param param1 the param1
   * @param param2 the param2
   * @return the keyword param wrapper
   */
  public KeywordParamWrapper
      getKeywordParamWrapper(String param1, String param2) {
    if (keywordParamWrapper == null) {
      keywordParamWrapper = new KeywordParamWrapper(this, param1, param2, conn);
    } else {
      keywordParamWrapper.setParam1(param1);
      keywordParamWrapper.setParam2(param2);
    }
    return keywordParamWrapper;
  }
}